|
![](/i/fill.gif) |
A while ago I was working on a big complicated image, and I wanted to
make a precise plane intersection shape far away from the origin. I
quickly realized that although I knew exact locations, planes are
described around the origin. It only takes three points to define a
plane, but for use in plane intersections there is an inside and an
outside, so I decided to use a fourth point to decide witch side of the
plane is inside. I thought I could write a macro to do it in 15
minutes, I was very wrong. I think it finally works now, but I thought
that a few days ago before I found some huge bugs. If you find any bugs
or have suggestions, please comment.
///////////////////////////////////////////////////////////////////
//
// Four_point_plane support functions
//
#macro Proj (U,V) // projection of U onto V
(V*(vdot(U,V)/vdot(V,V)))
#end
#macro Same_test (Vector1,Vector2) //tests if two vectors are the same
returns boolean
(vdot((Vector1 = Vector2),<1,1,1>) = 3)
#end
#macro Collinear_test (Vector1,Vector2,Vector3) //tests if three points
are on the same line
#local U = (Vector1-Vector2);
#local V = (Vector1-Vector3);
(abs(vdot(U,V)/(vlength(U)*vlength(V))) = 1)
#end
#macro On_plane_test (Point_on_plane,Normal,Test_point) // Uses a
point on the plane, and normal vector to test if Test_point
(vlength(Proj (Point_on_plane-Test_point,Normal)) = 0) // is on
the plane, returns boolean.
#end
#macro Same_direction_test (Vector1,Vector2) // Tests if two vectors
point in same direction. If either point is the zero vector,
(2*(vdot(Vector1,Vector2)/(vlength(Vector1)*vlength(Vector2)) =
1)-1) // you will get a divide by zero error.
#end
// Returns positive or negative 1.
#macro Same_side_test (Point_on_plane,Normal,Test_point1,Test_point2)
// Tests if both test points are on same side of plane.
#local Vec1 = Proj(Test_point1-Point_on_plane,Normal);
// If either test point is in the plane you will get a
#local Vec2 = Proj(Test_point2-Point_on_plane,Normal);
// divide by zero error. Returns positive or negative 1.
Same_direction_test (Vec1,Vec2)
#end
//
// End support functions
//
////////////////////////////////////////////////////////////////
// Four_point_plane
// In povray everything on one side of the plane is considered inside
the plane object
// Vector1, Vector2, and Vector3 are points on the plane, none of these
points can be the same as any other,
// and they can't be in a strait line. Inside point is a control point
to determine witch side of the plane
// is considered inside. Originally all of the error tests were just
going to be warning messages, but
// in testing I found that all of the errors the error trapping codes
are used to find would cause something
// like a divide by zero error before the warning message was
displayed. I decided then that it would be better
// to give a usefull error, and halt the render process, because the
render would be halted regardless.
#macro Four_point_plane (Vector1,Vector2,Vector3,Inside_point)
#if (Same_test (Vector1,Vector2))
#error "Vector1 = Vector2" #end
#if (Same_test (Vector1,Vector3))
#error "Vector1 = Vector3" #end
#if (Same_test (Vector3,Vector2))
#error "Vector2 = Vector3" #end
#if (Collinear_test (Vector1,Vector2,Vector3))
#error "All vectors on same line" #end
#local Cross =
vnormalize(vcross(Vector1-Vector2,Vector3-Vector2));
#if (On_plane_test(Vector1,Cross,Inside_point))
#error "Inside_point is on plane"#end
#if (On_plane_test(Vector1,Cross,<0,0,0>))
#local Distance_from_origin = 0;
#local Normal_vector = -Same_side_test
(Vector1,Cross,Cross,Inside_point)*Cross;
// If Cross vector points to the same side of the plane that
the inside point is on, inverts Cross to create normal vector.
#else
#local Test_n = Same_direction_test
(Cross,Proj(Vector1,Cross));
#local Test_o = Same_side_test
(Vector1,Cross,<0,0,0>,Inside_point);
#local Normal_vector = Test_n * Test_o * Cross;
#local Distance_from_origin = Test_o *
vlength(Proj(Vector1,Normal_vector));
#end
plane {Normal_vector, Distance_from_origin}
#end
// Three_point_plane assumes that the origin is in the object.
#macro Three_point_plane (Vector1,Vector2,Vector3)
Four_point_plane (Vector1,Vector2,Vector3,<0,0,0>) // lazy way
to do things
#end
/////////////////////////////////////////
// //
// More macros I have been working on //
// //
/////////////////////////////////////////
#macro Array_plane (Array) // creates a plane from data points stored
in an array
plane {<Array[1],Array[2],Array[3]>,Array[4]}
#end
#macro Inclusion (Object1,Object2) // Cuts a hole in an object and
fills it.
union
{difference{object{Object1}object{Object2}}object{Object2}}
#end
#macro Sign (X) //Positive or negative 1 depending on the sign of X
(X/abs(X))
#end
#macro Angle_between_vectors(U,V)
(degrees (acos(vdot(U,V)/(vlength(U)*vlength(V)))))
#end
#macro Three_Point_Angle (Vector1,Vector2,Vector3) //measures an angle
defined by three points the middle point is
Angle_between_vectors((Vector1-Vector2),(Vector3-Vector2))
//the vertex.
#end
////////////////////////////////////////
--
Dan Johnson
http://www.geocities.com/zapob
Post a reply to this message
|
![](/i/fill.gif) |